package com.company.project.web;

import com.company.project.config.WebMvcConfig;
import com.company.project.core.Result;
import com.company.project.core.ResultGenerator;
import com.company.project.core.common.CMDUtils;
import com.company.project.core.ocr.HeheOCRRecService;
import com.company.project.core.ocr.OCRRecService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.*;
import org.jsoup.select.Elements;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * =================================
 * <p>
 * Created by cjj on 21-11-12.
 * <p>
 * 描述:　pdf处理
 */

@RestController
@RequestMapping("/pdf")
@Api(tags = "pdf处理")
public class PdfController {

    @RequestMapping(value = "pdf2html", method = RequestMethod.POST)
    @ApiOperation(value = "pdf转换为html", notes = "pdf转换为html的接口")
    public Result pdf2html(MultipartFile file) {
        // 随机字符串，保证不重复
        String picName = UUID.randomUUID().toString();
        // 图片原始名字
        String oriName = file.getOriginalFilename();

        // 获取文件后缀名
        String extndName = oriName.substring(oriName.lastIndexOf("."));

        String name = picName + extndName;
        try {
            //文件的上传路径由配置文件里面决定
            file.transferTo(new File(name));
        } catch (IOException e) {
            e.printStackTrace();
            return ResultGenerator.genFailResult("文件上传异常");
        }
        //将pdf文件处理为html
        String htmlPath = "/pdf/" + name.substring(0, name.lastIndexOf('.')) + ".html";
        CMDUtils.pdfToHtmlByDockerInside(WebMvcConfig.FILEPATH + name, htmlPath);
        //将html 中的所有字体识别出来并找到对应关系
        Map<String, List<Font>> map = new HashMap<>();
        String imageBasePath = "/pdf/images/";
        File file1 = new File("/pdf");
        File[] files = file1.listFiles();
        String tmpFilePath = "";
        for (File file2 : files) {
            if (file2.getName().startsWith("pdf2htmlEX-")) {
                tmpFilePath = file2.getName();
                File[] files1 = file2.listFiles();
                for (File file3 : files1) {
                    if (file3.getName().endsWith(".woff")) {
                        String absolutePath = file3.getAbsolutePath();
                        System.out.println(absolutePath);
                        String name1 = file3.getName();
                        List<String> strings = CMDUtils.woff2Image(absolutePath, imageBasePath + name1);
                        System.out.println(strings.toString());
                        List<Font> list = new ArrayList<>();
                        for (String string : strings) {
                            String[] split = string.split(":");
                            if (split.length == 2 && NumberUtils.isCreatable(split[0])) {
                                Font font = new Font();
                                if ("space".equals(split[1])) {
                                    font.setCode(split[0]);
                                    font.setName(split[1]);
                                    font.setValue(" ");
                                } else {
                                    font.setCode(split[0]);
                                    font.setName(split[1]);
                                    font.setValue(" ");
                                }
                                list.add(font);
                            }
                        }
                        map.put(name1, list);
                    }
                }
            }
        }

        //通过ocr识别确认对应关系
        for (Map.Entry<String, List<Font>> stringListEntry : map.entrySet()) {
            String key = stringListEntry.getKey();
            String imagePath = imageBasePath + key + ".png";
            String recResult = "";
            try {
                System.out.println(imagePath);
                recResult = OCRRecService.recStr(HeheOCRRecService.ORC_URL, imagePath);
            } catch (Exception e) {
                e.printStackTrace();
            }
            String replace = recResult.replace("\n", "").replace(" ", "");
            replace = replace.substring(1, replace.length() - 2);
            System.out.println(replace);
            List<Font> value = stringListEntry.getValue();
            System.out.println(value.stream().map(font -> font.getName()).reduce((f1, f2) -> f1 + "," + f2).orElse(""));
            System.out.println("字体数组大小:" + value.size() + " ocr识别长度:" + replace.length());
            if (replace.length() + 1 == value.size()) {
                for (int i = 0; i < value.size(); ) {
                    Font font = value.get(i);
                    if (!font.getName().equals("space")) {
                        String substring = replace.substring(i - 1, i);
                        font.setValue(substring);
                    }
                    i++;
                }
            } else {
                //识别不准确的进行二次单独识别
                String newPath = "/pdf/" + tmpFilePath + "/" + key;
                String targetPath = newPath + "split/";
                CMDUtils.woff2Image2(newPath, targetPath);
                for (int i = 0; i < value.size(); i++) {
                    Font font = value.get(i);
                    if (font.getName().equals("space")) {
                        continue;
                    } else {
                        try {
                            String imagePath2 = targetPath + (i + 1) + ".png";
                            System.out.println(imagePath2);
                            recResult = OCRRecService.recStr(HeheOCRRecService.ORC_URL, imagePath2);
                            replace = recResult.replace("\n", "").replace(" ", "").trim();
                            if (replace.length() <= 3) {
                                System.out.println(replace);
                                font.setValue(" ");
                            } else {
                                String substring = replace.substring(1, replace.length() - 2);
                                if (substring.length() == 1) {
                                    font.setValue(substring);
                                } else {
                                    font.setValue(substring);
                                    System.out.println(substring);
                                }
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }

                }
            }
        }
        CMDUtils.deleteFileOnServer("/pdf/" + tmpFilePath);

        htmlModify(htmlPath, map, WebMvcConfig.FILEPATH + name + ".html");
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String ip = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort();
        return ResultGenerator.genSuccessResult(ip + "/file/" + name + ".html");
    }

    public static void main(String[] args) throws IOException {

        PdfController pdfController = new PdfController();

        Map<String, List<Font>> map = new HashMap<>();
        ArrayList<Font> objects = new ArrayList<>();
        Font font = new Font();
        font.setCode("34");
        font.setName("quotedbl");
        font.setValue("(");
        objects.add(font);
        Font font1 = new Font();
        font1.setCode("35");
        font1.setName("numbersign");
        font1.setValue(")");
        objects.add(font1);
        map.put("f5d.woff", objects);
        pdfController.htmlModify("/home/cjj/下载/bbb.html", map, "/home/cjj/下载/bbb1.html");

    }


    public void htmlModify(String htmlPath, Map<String, List<Font>> map, String newHtmlPath) {
        //将html文件中的字体替换，并切换为通用的字体
        File htmlFile = new File(htmlPath);
        Document doc = null;
        try {
            doc = Jsoup.parse(htmlFile, StandardCharsets.UTF_8.name());
            doc.outputSettings().prettyPrint(false);
            Elements style = doc.select("style");
            for (Element element : style) {
                String text = element.html();
                String[] split = text.split("\n");
                StringBuilder accum = new StringBuilder();
                for (String s : split) {
                    String lastIndexStr = "font-family:";
                    int ff1 = s.lastIndexOf(lastIndexStr);
                    if (ff1 > -1) {
                        String substring1 = s.substring(0, ff1);
                        String substring2 = s.substring(ff1);
                        int ff2 = substring2.indexOf(";line-height");
                        if (ff2 > -1) {
                            String substring3 = substring2.substring(ff2);
                            accum.append(substring1 + "font-family:Open Sans" + substring3);
                        } else {
                            accum.append(s);
                        }
                    } else {
                        accum.append(s);
                    }
                    accum.append("\n");
                }
                element.html(accum.toString());
            }

            //将html中对应的内容修改
            for (Map.Entry<String, List<Font>> stringListEntry : map.entrySet()) {
                String key = stringListEntry.getKey();
                key = "f" + key.substring(0, key.lastIndexOf('.'));
                List<Font> value = stringListEntry.getValue();
                //获取所有元素
                Elements select = doc.select("div." + key);
                for (Element element : select) {
                    deepElement(element, value, map);
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        // 将元素写入文件中
        try (BufferedWriter osw = new BufferedWriter(new FileWriter(newHtmlPath))) {
            osw.write(doc.html());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void deepElement(Node node, List<Font> value, Map<String, List<Font>> map) {
        List<Node> nodess = node.childNodes();
        for (Node nodee : nodess) {
            if (nodee instanceof TextNode) {
                TextNode textNode = (TextNode) nodee;
                String text = textNode.text();
                String tmpstr = "";
                for (int i = 0; i < text.length(); i++) {
                    int c = (int) text.charAt(i);
                    for (Font font : value) {
                        String code = font.getCode();
                        if (code.equals(String.valueOf(c))) {
                            tmpstr += font.getValue();
                            break;
                        }
                    }
                }
                System.out.println("替换原内容：" + text + ";替换内容:" + tmpstr);
                textNode.text(tmpstr);
            } else if (nodee instanceof Element) {
                Element element1 = (Element) nodee;
                String aClass = element1.attr("class");
                List<Font> fonts = null;
                if (StringUtils.isNotBlank(aClass) && aClass.startsWith("f")) {
                    System.out.println(aClass);
                    String key = aClass.substring(1, 3) + ".woff";
                    fonts = map.get(key);
                }
                //英文对应不上，只能移除这个样式
                if (StringUtils.isNotBlank(aClass) && aClass.startsWith("_ _")) {
                    element1.attr("class", "");
                }
                if (fonts != null) {
                    deepElement(element1, fonts, map);
                } else {
                    deepElement(element1, value, map);
                }
            } else {
                System.out.println(nodee.toString() + ":" + nodee.nodeName());
            }
        }
    }


    @Data
    static class Font {
        private String code;
        private String name;
        private String value;
    }

}
